package org.sgx.gwteditors.client.impl1.complex;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.sgx.gwteditors.client.editor.Editor;
import org.sgx.gwteditors.client.editor.EditorNotFound;
import org.sgx.gwteditors.client.editor.Types;
import org.sgx.gwteditors.client.editor.error.EditorError;
import org.sgx.gwteditors.client.editor.error.EditorErrorManager;
import org.sgx.gwteditors.client.editor.event.EditorEventManager;
import org.sgx.gwteditors.client.editor.event.ValueChangeListener;
import org.sgx.gwteditors.client.editor.props.PropertyHaver;
import org.sgx.gwteditors.client.impl1.EditorFramework1;
import org.sgx.gwteditors.client.impl1.EditorManager1;

import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * matrix 2d editor, all members must be same type. This editor will only show a 
 * "name" for each object. Only when the name is clicked the subeditor will be 
 * showed. 
 * 
 * @author sg
 */
public class Array1DEditor2<T extends PropertyHaver> extends FlexTable implements Editor<T[]> {

	public static interface Namer {
		String getName(Object t);
	}

	static Logger logger = Logger.getLogger(Array1DEditor2.class + "");
	Map<Integer, Editor<T>> eds = null;
//	private int imax;
//	private int jmax;
	private Object[] model;
//	private String type;
	private boolean vertical;
	private Namer namer;
	
	public Namer DEFAULT_NAMER = new Namer() {
		@Override
		public String getName(Object t) {
			return t == null ? "false" : t + "";
		}
	};

	
	public Array1DEditor2() {
		this(true, null); 
	}
	public Array1DEditor2(boolean vertical, Namer namer) {
		super();
		eds = new HashMap<Integer, Editor<T>>();
//		this.type = type;
		this.vertical = vertical;
		this.namer = namer;
		if(namer==null)
			this.namer = DEFAULT_NAMER; 
	}

	@Override
	public void addValueChangeListener(ValueChangeListener<T[]> l) {
		EditorEventManager.<T[]> getInstance().addValueChangeListener(this, l);
	}

	@Override
	public void removeValueChangeListener(ValueChangeListener<T[]> l) {
		EditorEventManager.<T[]> getInstance().addValueChangeListener(this, l);
	}

	@Override
	public List<EditorError<T[]>> getErrors() {
		return EditorErrorManager.<T[]> getInstance().getErrors(this);
	}

	@Override
	public T[] flush() {
//		T[] vals = (T[]) new Object[imax][jmax];
//		for (int i = 0; i < this.imax; i++) {
//			Editor<T> ed = eds.get(i);
//			if (ed == null)
//				continue;
//			T val = (T) ed.flush();
//			vals[i] = val;
//		}
//		return vals;// no validation / errors
		return null;
	}

	@Override
	public void load(T[] model) {

		if (model == null)
			return;
		// clear the table
		clear();
		
		this.model = model;
//		this.imax = model.length;
		for (int i = 0; i < model.length; i++) {
			T o = model[i];
//			System.out.println(o); 
			if (o == null)
				continue;
			Editor<T> ed = null;
			try {
				ed = Types.getInstance().newEditor(EditorFramework1.TYPE_PROPERTYHAVER);// EditorFactoryImpl.<Object>getInstance().getEditorForObject(o);
				final Widget w = ed.getWidget(); 
				ed.load(o);
				
				String name = namer.getName(o);

				/* due to a bug in the slider component http://code.google.com/p/gwt-slider-bar/issues/detail?id=5
				 * we need to first open the DP ,. then add the content and then close the DP.
				 */				
				final DisclosurePanel dp = new DisclosurePanel(name);				
//				dp.setOpen(true); 
				dp.setAnimationEnabled(true);
				dp.setOpen(false); 
				dp.addOpenHandler(new OpenHandler<DisclosurePanel>() {					
					@Override
					public void onOpen(OpenEvent<DisclosurePanel> event) {
						if(event.getTarget().isOpen()) {
							dp.setContent(w);
						}
					}
				}); 
//				Element e = dp.getHeader().getElement();
//				DOMUtil.addEventHandler(e, "click", new EventHandler() {					
//					@Override
//					public void onEvent(Event event) {
//						System.out.println("YYYYYY");
//					}
//				}, false); 
				
//				if(dp.getHeader() instanceof HasMouseDownHandlers) {
//					System.out.println("yes");
//				}
//				else {
//					System.out.println("no: "+dp.getHeader().getClass());
//				}
				if (vertical) {
					setWidget(i, 1, dp);
					 
					//add/remove buttons
					HorizontalPanel hp = new HorizontalPanel();
					
					Anchor addButton = new Anchor("add");
					Anchor rmButton = new Anchor("remove");
					hp.add(addButton); 
					hp.add(new HTML("<span>&nbsp;</span>")); 
					hp.add(rmButton); 
					setWidget(i, 0, hp);					
					getCellFormatter().setVerticalAlignment(i, 0, HasVerticalAlignment.ALIGN_TOP);
					
				}
				else {
					setWidget(1, i, dp);
				}

				eds.put(i, ed);
			} catch (EditorNotFound e) {
				logger.log(Level.WARNING, " exception building editor for field " + i + ", class: " + o.getClass()
						+ " : " + o + ". Cause: " + e.getCause() + " - " + e.getMessage());
				e.printStackTrace();
			}
			// this.jmax=model[i].length;
			// for(int j=0; j<model[i].length; j++) {
			// Object o = model[i][j];
			// if(o==null)
			// continue;
			// Editor<Object> ed=null;
			// try {
			// ed = EditorFactoryImpl.<Object>getInstance().getEditorForObject(o);
			// ed.load(o);
			// setWidget(i, j, ed.getWidget());
			// eds.put(i+","+j, ed);
			// } catch (EditorNotFound e) {
			// logger.log(Level.WARNING, " exception building editor for field "+i+
			// ", "+j+", class: "+model[i][j].getClass()+" : "+o+
			// ". Cause: "+e.getCause()+" - "+e.getMessage());
			// e.printStackTrace();
			// }
			// }
		}
	}

	@Override
	public Widget getWidget() {
		return this;
	}

	@Override
	public boolean isSimple() {
		return false;
	}

	@Override
	public String getEditorId() {
		return EditorManager1.getInstance().getEditorName(this);
	}

	@Override
	public String[] getEditorTypesSupported() {
		return null; // String[]{EditorFramework1.TYPE_};
	}

}
